home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part2 / 14930 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  3.7 KB

  1. Path: mayne.ugrad.cs.ubc.ca!not-for-mail
  2. From: c2a192@ugrad.cs.ubc.ca (Kazimir Kylheku)
  3. Newsgroups: comp.lang.c,comp.unix.programmer
  4. Subject: Re: Q: '\n' character
  5. Date: 15 Apr 1996 16:33:14 -0700
  6. Organization: Computer Science, University of B.C., Vancouver, B.C., Canada
  7. Message-ID: <4kumbqINNgcr@mayne.ugrad.cs.ubc.ca>
  8. References: <4kj66f$k0o@ren.cei.net> <AD97189A966891F2@mcdiala02.it.luc.edu> <4ktn04INNoev@keats.ugrad.cs.ubc.ca> <4ku8f9$d3o@mark.ucdavis.edu>
  9. NNTP-Posting-Host: mayne.ugrad.cs.ubc.ca
  10.  
  11. In article <4ku8f9$d3o@mark.ucdavis.edu>,
  12. James Knight <knight@quad.cs.ucdavis.edu> wrote:
  13.  
  14. This is a good effort: I will try to look for any marginal improvements.
  15.  
  16.  
  17.  >/*
  18.  > * my_getline
  19.  > *
  20.  > * Read a line of any length, store it in an internal buffer, and 
  21.  > * return the internal buffer (along with a length value if desired).
  22.  > *
  23.  > * NOTE: Each line read will overwrite the previous line read.  So,
  24.  > *       make a copy of any line you want to keep around.
  25.  > *
  26.  > * Parameters:
  27.  > *     fp - A FILE pointer open for reading.
  28.  > *     len_out - Address to where to store the line length.
  29.  > *
  30.  > * Returns:
  31.  > *     An internal buffer containing the line, or NULL on EOF or error.
  32.  > */
  33.  >char *my_getline(FILE *fp, int *len_out)
  34.  >{
  35.  >  static int bufsize = 0;
  36.  >  static char *buffer = NULL;
  37.  >  int size, len, flag;
  38.  >
  39.  >  /*
  40.  >   * Initialize the internal buffer, if necessary.
  41.  >   */
  42.  >  if (buffer == NULL) {
  43.  >    bufsize = 128;
  44.  >    if ((buffer = malloc(bufsize)) == NULL)
  45.  >      return NULL;
  46.  >  }  
  47.  >
  48.  >  /*
  49.  >   * Read the first part of the line.
  50.  >   */
  51.  >  flag = 0;
  52.  >  buffer[bufsize-2] = '\0';
  53.  >
  54.  >  if (fgets(buffer, bufsize, fp) == NULL)
  55.  >    return NULL;
  56.  >  else if (buffer[bufsize-2] == '\0' || buffer[bufsize-2] == '\n') {
  57.  >    len = strlen(buffer);
  58.  >    flag = 1;
  59.  >  }
  60.  >
  61.  >  /*
  62.  >   * If the line is longer, then realloc the internal buffer and
  63.  >   * read the next section of the line.
  64.  >   */
  65.  >  while (!flag) {
  66.  >    size = bufsize - 1;
  67.  >    bufsize += bufsize;
  68.  
  69. That's excellent! O(log n) reallocs with respect to line length. This exceeds
  70. my expectation for a linear reallocation strategy. An increase in size that
  71. follows the fibonacci sequence might be good as well.
  72.  
  73.  >    if ((buffer = realloc(buffer, bufsize)) == NULL)
  74.  >      return NULL;
  75.  
  76. Just one quip: when realloc() fails, the original data is not lost. So you have
  77. to keep the original pointer around, and be ready to either leave the data as
  78. it is, or free() it.
  79.  
  80.  >    buffer[bufsize-2] = '\0';
  81.  >    if (fgets(buffer + size, bufsize - size, fp) == NULL) {
  82.  >      len = size;
  83.  >      flag = 1;
  84.  >    }
  85.  >    else if (!buffer[bufsize-2] || buffer[bufsize-2] == '\n') {
  86.  >      len = size + strlen(buffer + size);
  87.  >      flag = 1;
  88.  >    }
  89.  >  }
  90.  >
  91.  >  /*
  92.  >   * Strip the newline from the line, if it's there.
  93.  >   */
  94.  >  if (buffer[len-1] == '\n')
  95.  >    buffer[--len] = '\0';
  96.  >
  97.  >  if (len_out) *len_out = len;
  98.  >  return buffer;
  99.  
  100. Ah, you forgot to adjust the buffer size for the actual length read! If the
  101. line is 128K plus one byte, you will return 256K---the next higher power of
  102. two. No biggie, but it's easy to fix with a realloc down to the actual size.
  103. I'm not sure how paranoid one ought to be when checking the result of a
  104. _shrinking_ realloc, but I'd treat it the same was as a growing one to be safe.
  105.  
  106.  >}
  107.  >
  108.  
  109. Nevertheless, my original comments about fgets() versus loops that use getc()
  110. apply: the above might be quite a bit cleaner if you were content to spoon out
  111. a character at a time. No strlen(), no odd buffer manipulation---just a pointer
  112. that you advance, and check against the buffer bounds.
  113.  
  114. What about dealing with null characters in the input lines?
  115.  
  116. -- 
  117. I'm not really a jerk, but I play one on Usenet.
  118.